package com.softeem.gulimail.product.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.softeem.gulimail.product.vo.Catalog2Vo;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import java.util.*;
import java.util.stream.Collectors;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.softeem.common.utils.PageUtils;
import com.softeem.common.utils.Query;
import com.softeem.gulimail.product.dao.CategoryDao;
import com.softeem.gulimail.product.entity.CategoryEntity;
import com.softeem.gulimail.product.service.CategoryService;
import org.springframework.util.StringUtils;


@Service("categoryService")
public class CategoryServiceImpl extends ServiceImpl<CategoryDao, CategoryEntity> implements CategoryService {
    @Autowired
    private StringRedisTemplate srt;
    @Autowired
    RedissonClient redisson;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {

        IPage<CategoryEntity> page = this.page(
                new Query<CategoryEntity>().getPage(params),
                new QueryWrapper<CategoryEntity>()
        );

        return new PageUtils(page);
    }

    @Override
    public List<CategoryEntity> listWithTree() {
        List<CategoryEntity> categoryEntities = baseMapper.selectList(null);
        List<CategoryEntity> level1Menus = categoryEntities.stream()
                                           .filter(categoryEntity -> categoryEntity.getParentCid() == 0)
                                           .map(category ->  {
                                               category.setChildren(getChildrens(category,categoryEntities));
                                               return category;
                                           })
                                           .sorted((c1,c2) -> Integer.compare(c1.getSort(),c2.getSort()))
                                           .collect(Collectors.toList());

        return level1Menus;
    }

    @Override
    public void removeMenuByIds(List<Long> asList) {
        //TODO 1.检查当前删除的菜单，是否被别的地方引用

        //逻辑删除，物理删除就真没了
        baseMapper.deleteBatchIds(asList);
    }
    @Cacheable(value = {"category-level1"},key = "'getlevelCategory'")
    @Override
    public List<CategoryEntity> getLevelCategory() {
        System.out.println("经过数据库查询。。。");
        List<CategoryEntity> list = baseMapper.selectList(new QueryWrapper<CategoryEntity>().eq("parent_cid", 0));
        return list;
    }

    @Override
    public Map<String, List<Catalog2Vo>> getCatelogJson(){
        String catalogJSON = srt.opsForValue().get("catalogJSON");
        if(StringUtils.isEmpty(catalogJSON)){
            Map<String, List<Catalog2Vo>> catelogJsonFromDb = getCateLogJsonFromDbWithRedisLock();
            return catelogJsonFromDb;
        }
        Map<String, List<Catalog2Vo>> map = JSON.parseObject(catalogJSON, new TypeReference<Map<String, List<Catalog2Vo>>>() {
        });
        return map;
    }
    public Map<String, List<Catalog2Vo>> getCateLogJsonFromDbWithRedisLock(){


        return getDataFromDb();
    }

    public Map<String, List<Catalog2Vo>> getCatelogJsonFromDbWithLocalLock() {
        //通过本地锁的方式
        synchronized (this){
            return getDataFromDb();
        }




//        //获取所有一级分类的list集合
//        List<CategoryEntity> levelCategory = getLevelCategory();
//        //创建最终返回的map集合  key是一级分类的id，value是catalog2vo，即当前分类下的二级分类取出来的vo
//        Map<String,List<Catalog2Vo>> map = new HashMap<>();
//        //遍历一级分类，目的是获得一级分类的cat_Id
//        for(CategoryEntity c1:levelCategory){
//            //创建二级分类对应vo的集合
//            List<Catalog2Vo> list1 = new ArrayList<>();
//            //通过二级的类的父id，找到对应的二级分类
//            List<CategoryEntity> categoryEntities = baseMapper.selectList(new QueryWrapper<CategoryEntity>().eq("parent_cid", c1.getCatId()));
//            //判断是否为空，如果当前二级分类为空，则后续不执行
//            if(categoryEntities!=null){
//                //遍历二级分类，1.通过二级分类的id，找到三级分裂 2.将二级分类中对应的值放到vo中
//                for(CategoryEntity c2:categoryEntities){
//                    //通过二级分类的id，获取三级分类
//                    List<CategoryEntity> categoryEntities1 = baseMapper.selectList(new QueryWrapper<CategoryEntity>().eq("parent_cid", c2.getCatId()));
//                    //创建三级分类对应的vo集合，二级分类的vo中有一个三级分类的集合就是这
//                    List<Catalog2Vo.Catalog3Vo> list = new ArrayList<>();
//                    //如果当前三级分类为空，则不执行
//                    if(categoryEntities1!=null){
//                        //遍历三级分类，将三级分类中对应的属性放到三级vo中
//                        for(CategoryEntity c3:categoryEntities1){
//                            //创建三级分类的vo，三级分类为一个集合，承载这个分类的vo也是一个集合，这个集合将会被放到二级vo中的对应属性中
//                            Catalog2Vo.Catalog3Vo catalog3Vo = new Catalog2Vo.Catalog3Vo(c2.getCatId().toString(), c3.getCatId().toString(), c3.getName());
//                            //添加三级vo
//                            list.add(catalog3Vo);
//                        }
//                    }
//                    /**
//                     * 创建二级vo，所需的三级vo的集合在上边已经创建，二级分类为一个集合，使用一个二级vo的list集合承载
//                     */
//                    Catalog2Vo catalog2Vo = new Catalog2Vo(c1.getCatId().toString(), list, c2.getCatId().toString(), c2.getName());
//                    list1.add(catalog2Vo);
//                }
//            }
//            //将数据放到一个map集合中，key为一级分类的id，value为二级vo的list集合
//            map.put(c1.getCatId().toString(),list1);
//        }
//        return map;
    }

    private Map<String, List<Catalog2Vo>> getDataFromDb() {
        String catalogJSON = srt.opsForValue().get("catalogJSON");
        if(!StringUtils.isEmpty(catalogJSON)){
            Map<String, List<Catalog2Vo>> map = JSON.parseObject(catalogJSON,new TypeReference<Map<String, List<Catalog2Vo>>>(){});
            return map;
        }else {
            List<CategoryEntity> categoryList = baseMapper.selectList(null);
            List<CategoryEntity> level1Categorys = getCategoryEntities(categoryList,0l);
            Map<String, List<Catalog2Vo>> collect2 = level1Categorys.stream().collect(Collectors.toMap(cat -> cat.getCatId().toString(), v -> {
//            此处查到的是二级分类
                List<CategoryEntity> categoryEntities = getCategoryEntities(categoryList,v.getCatId());
                List<Catalog2Vo> collect = null;
                if(categoryEntities!=null){
                    collect = categoryEntities.stream().map(item -> {
//                此处查到的的是三级分类
                        List<CategoryEntity> categoryEntities1 = getCategoryEntities(categoryList,item.getCatId());
                        Catalog2Vo catalog2Vo = null;
                        if(categoryEntities1!=null){
                            List<Catalog2Vo.Catalog3Vo> collect1 = categoryEntities1.stream().map(l3 -> {
                                Catalog2Vo.Catalog3Vo catalog3Vo = new Catalog2Vo.Catalog3Vo(item.getCatId().toString(), l3.getCatId().toString(), l3.getName());
                                return catalog3Vo;
                            }).collect(Collectors.toList());
                            catalog2Vo = new Catalog2Vo(v.getCatId().toString(), collect1, item.getCatId().toString(), item.getName());
                        }
                        return catalog2Vo;
                    }).collect(Collectors.toList());
                }
                return collect;
            }));
            String s = JSON.toJSONString(collect2);
            srt.opsForValue().set("catalogJSON",s);
            return collect2;
        }
    }

    private List<CategoryEntity> getCategoryEntities(List<CategoryEntity> categoryList,Long parent_cid) {

        return categoryList.stream().filter(item -> item.getParentCid()==parent_cid).collect(Collectors.toList());
    }

    public List<CategoryEntity> getChildrens(CategoryEntity c,List<CategoryEntity> categoryEntities){
        List<CategoryEntity> collect = categoryEntities.stream()
                .filter(category -> c.getCatId() == category.getParentCid())
                .map(cate -> {
                    cate.setChildren(getChildrens(cate, categoryEntities));
                    return cate;
                })
                .sorted((c1, c2) -> c1.getSort()==null?0:c1.getSort().compareTo(c2.getSort()==null?0:c1.getSort()))
                .collect(Collectors.toList());
        return collect;
    }


}